using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;

namespace BTS_Utilities
{
    public static class StatusMessageParser
    {
        /// <summary>
        /// Loops through the document at the specified XPath query and sets the value
        /// </summary>
        /// <param name="Document"></param>
        /// <param name="NamespaceID">ns0</param>
        /// <param name="Namespace">http://healthcareclaims</param>
        /// <param name="XPathToParent">"/ns0:Request/ns0:sync/ns0:after"</param>
        /// <param name="ItemName">ProcessingStatusCode</param>
        /// <param name="ItemValue">aa</param>
        /// <param name="ItemType">Attibute</param>  Could be Attribute or Element
        public static void LoopAndSetItemValue(XmlDocument Document, string NamespaceID, string Namespace, string XPathToParent, string ItemName, string ItemValue, string ItemType)
        {
        XmlNamespaceManager _mgr = new XmlNamespaceManager(Document.NameTable);
            _mgr.AddNamespace(NamespaceID, Namespace);
                XmlNodeList nodes = Document.SelectNodes(XPathToParent, _mgr);
                foreach (XmlNode node in nodes)
                {
                    foreach (XmlNode child in node.ChildNodes)
                    {
                        if (ItemType.ToLower() == "element")
                        {
                            foreach (XmlNode grandChild in child.ChildNodes)
                            {
                                if (grandChild.Name == ItemName)
                                {
                                    grandChild.Value = ItemValue;
                                }
                            }
                        }
                        else
                        {
                            foreach (XmlAttribute childAttrib in child.Attributes)
                            {
                                if (childAttrib.Name == ItemName)
                                {
                                    childAttrib.Value = ItemValue;
                                }
                            }
                        }
                    }
                }
            
            
        }
        /// <summary>
        /// Loop and set with fully qualified XPATH
        /// </summary>
        /// <param name="Document"></param>
        /// <param name="XPath"></param>
        /// <param name="InnerText"></param>
        public static void LoopAndSetFromQualifiedXPath(XmlDocument Document, string XPath, string InnerText)
        {
            XmlNodeList _nodes = Document.SelectNodes(XPath);
            foreach (XmlNode node in _nodes)
            {
                node.InnerText = InnerText;
            }
        }
        /// <summary>
        /// Loops through the document at the specified XPath query and sets the value.  This differs from the above method in that it only loops
        /// on the nodes returned by the XPATH and not on children nodes of that nodeset
        /// Sample below
        /// LoopAndSetItemValueFromRoot(_doc, "ns0", @"http://HealthcareClaimSchemas.BAM.BAM_Activity_Schema", "/ns0:Root/EB_270_RequestInquiry", "CommunicationMethod", "testme", "element")
        /// </summary>
        /// <param name="Document"></param>
        /// <param name="NamespaceID">ns0</param>
        /// <param name="Namespace">http://healthcareclaims</param>
        /// <param name="XPathToParent">"/ns0:Request/ns0:sync/ns0:after"</param>
        /// <param name="ItemName">ProcessingStatusCode</param>
        /// <param name="ItemValue">aa</param>
        /// <param name="ItemType">Attibute</param>  Could be Attribute or Element
        public static void LoopAndSetItemValueFromRoot(XmlDocument Document, string NamespaceID, string Namespace, string XPathToParent, string ItemName, string ItemValue, string ItemType)
        {
            XmlNamespaceManager _mgr = new XmlNamespaceManager(Document.NameTable);
            _mgr.AddNamespace(NamespaceID, Namespace);
            XmlNodeList nodes = Document.SelectNodes(XPathToParent, _mgr);
            foreach (XmlNode node in nodes)
            {
                foreach (XmlNode child in node.ChildNodes)
                {
                    if (ItemType.ToLower() == "element")
                    {
                        
                            if (child.Name.ToLower() == ItemName.ToLower())
                            {
                                child.InnerText = ItemValue;
                            }
                    }
                    else
                    {
                        foreach (XmlAttribute childAttrib in child.Attributes)
                        {
                            if (childAttrib.Name.ToLower() == ItemName.ToLower())
                            {
                                childAttrib.Value = ItemValue;
                            }
                        }
                    }
                }
            }


        }
        /// <summary>
        /// Loops through the document at the specified XPath query and returns the number of child iterations
        /// </summary>
        /// <param name="Document"></param>
        /// <param name="NamespaceID">ns0</param>
        /// <param name="Namespace">http://healthcareclaims</param>
        /// <param name="XPathToParent">"/ns0:Request/ns0:sync/ns0:after"</param>
        /// <param name="ItemName">ProcessingStatusCode</param>
        /// <param name="ItemValue">aa</param>
        /// <param name="ItemType">Attibute</param>  Could be Attribute or Element
        public static int GetChildCount(XmlDocument Document, string XPathToParent)
        {
            XmlNodeList nodes = Document.SelectNodes(XPathToParent);
            int i = 0;
            return nodes.Count;   
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Document"></param>
        /// <param name="NamespaceID"></param>
        /// <param name="Namespace"></param>
        /// <param name="XPathToParent"></param>
        /// <param name="IteratorValue"></param>
        /// <returns></returns>
        public static int GetRepeatingValue(XmlDocument Document, string NamespaceID, string Namespace, string XPathToParent, int IteratorValue)
        {
            
            XmlNamespaceManager _mgr = new XmlNamespaceManager(Document.NameTable);
            if (NamespaceID != null)
            {
                _mgr.AddNamespace(NamespaceID, Namespace);
            }
            if (NamespaceID == null)
            {
                if (Namespace != null) { _mgr.AddNamespace(string.Empty, Namespace); };
            }
            XmlNode nodeInfo = Document.SelectNodes(XPathToParent, _mgr).Item(IteratorValue);

            
            return 0;
            

        }
        public static string GetFirstChildInnerXML(XmlDocument Document)
        {
            return Document.FirstChild.InnerXml.ToString();
        }
        public static string GetInnerXML(XmlDocument Document)
        {
            return Document.InnerXml.ToString();
        }
        public static void SetValue(XmlDocument Document, string NamespaceID, string Namespace, string XPathToItem, string ItemValue)
        {
            XmlNamespaceManager _mgr = new XmlNamespaceManager(Document.NameTable);
            _mgr.AddNamespace(NamespaceID, Namespace);
            try
            {
                XmlNode _node = Document.SelectSingleNode(XPathToItem, _mgr);
                _node.InnerText = ItemValue;
            }
            catch (System.Exception emsg)
            {
                //Do nothing - In production this would have to change
            }
        }
        /// <summary>
        /// /// SetValueForType(_doc, "ns0", @"http://HealthcareClaimSchemas.BAM.BAM_Activity_Schema", "/ns0:Root/EB_270_RequestInquiry", "CommunicationMethod", "testme", "element")
        /// </summary>
        /// <param name="Document"></param>
        /// <param name="NamespaceID"></param>
        /// <param name="Namespace"></param>
        /// <param name="XPathToItem"></param>
        /// <param name="ItemValue"></param>
        /// <param name="ItemType"></param>
        public static void SetValueForAttribute(XmlDocument Document, string NamespaceID, string Namespace, string XPathToParent, string AttributeName, string AttributeValue)
        {
            XmlNamespaceManager _mgr = new XmlNamespaceManager(Document.NameTable);
            _mgr.AddNamespace(NamespaceID, Namespace);
            try
            {
                XmlNode _node = Document.SelectSingleNode(XPathToParent, _mgr);
                _node.Attributes[AttributeName].Value = AttributeValue;
                
            }
            catch (System.Exception emsg)
            {
                //Do nothing - In production this would have to change
            }
        }
        /// <summary>
        /// Gets value of a repeating attribute
        /// Example: BTS_Utilities.StatusMessageParser.GetSingleValueOfRepeatingSegmentAttribute(_doc, "ns0", @"http://schemas.wpc-edi.com/X12/ISOMORPH/HIPAA/4010A1/TS270A1", "/ns0:X12_4010_270/ns0:TS270A1_2000A/ns0:TS270A1_2100A/ns0:TS270A1_2100A_NM1_InformationSourceName","TS270A1_2100A_NM109__InformationSourcePrimaryIdentifier")
        /// </summary>
        /// <param name="Document"></param>
        /// <param name="NamespaceID"></param>
        /// <param name="Namespace"></param>
        /// <param name="XPathToNode"></param>
        /// <param name="AttributeName"></param>
        /// <returns></returns>
        public static string GetSingleValueOfRepeatingSegmentAttribute(XmlDocument Document, string NamespaceID, string Namespace, string XPathToNode, string AttributeName)
        {
            XmlNamespaceManager _mgr = new XmlNamespaceManager(Document.NameTable);
            _mgr.AddNamespace(NamespaceID, Namespace);

            XmlNode _node = Document.SelectSingleNode(XPathToNode, _mgr);
            return _node.Attributes[AttributeName].Value.ToString();
                
            
        }
        /// <summary>
        /// Send in the variables from the document and this will construct the string needed for the HTTP Header in BTS
        /// Outbound270(HTTP.UserHttpHeaders)= this string in an construct message - expression shape
        /// </summary>
        /// <param name="PrimarySourceID"></param>
        /// <param name="ProviderTransactionIdentifier"></param>
        /// <returns></returns>
        public static string SetHTTPHeaderInfoForAvaility(string PrimarySourceID, string ProviderTransactionIdentifier)
        {
            return "TranCode:270\r\nMessageFormat:X12\r\nSender:testmicrosoft\r\nReceiver:" + PrimarySourceID + "\r\nSession:\r\nProviderOfficeNbr:\r\nProviderTransID:" + ProviderTransactionIdentifier;
        }

        /// <summary>
        /// Check for the HTTP Return Value if it is an error return True if not return False.
        /// </summary>
        /// <param name="XPATH"></param>
        /// <returns></returns>
        public static bool CheckForAvailityX12Response(string XPATH, XmlDocument Document)
        {
            string messageFormat = Document.SelectSingleNode(XPATH).InnerText;
            bool retVal = false;
            if (messageFormat == "X12")
            {
                retVal = true;
            }
            else
            {
                retVal = false;
            }
            return retVal;
        }
        public static bool CheckForAvailityHTTPError(string XPATHTranCode, XmlDocument Document)
        {
            //VT are Error Codes from Availity.  This happens when Availity cannot validate the Message
            string TranCode = Document.SelectSingleNode(XPATHTranCode).InnerText;
            if (TranCode.ToLower().Contains("vt"))
            {
                return true;
            }
            else
            {
                //No Availity Error Message.  Lets try to determine if there is a Payer Generated Error Message
                if(CheckForAvailityPayerGeneratedHTTPError(@"/*[local-name()='ENVELOPE' and namespace-uri()='http://HealthcareClaimSchemas.Availity.Availity_HTTP_AXIML_Response']/*[local-name()='BODY' and namespace-uri()='']/*[local-name()='TransactionSet' and namespace-uri()='']/*[local-name()='Errors' and namespace-uri()='']", Document))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            
        }
        public static bool CheckForAvailityPayerGeneratedHTTPError(string XPATHErrorNode, XmlDocument Document)
        {
            //Availity can validate the message but the Payer can issue an error response.  This checks for that error
            XmlNodeList nodes = Document.SelectNodes(XPATHErrorNode);
            if(nodes.Count > 0)
            {
                return true;
            }
            else
            {
                return false;
            }

        }
        public static string GetInnerXMLFromXPATH(XmlDocument document, string XPATHStatement)
        {
            return document.SelectSingleNode(XPATHStatement).InnerXml;
        }
        public static string GetInnerTEXTFromXPATH(XmlDocument document, string XPATHStatement)
        {
            return document.SelectSingleNode(XPATHStatement).InnerText;
        }
       
        
    }
}
